package com.zaofan.mobile.controller;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.dbutils.QueryRunner;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.zaofan.bean.Account;
import com.zaofan.bean.AccountLog;
import com.zaofan.bean.Error;
import com.zaofan.bean.Goods;
import com.zaofan.bean.GoodsOrderDetail;
import com.zaofan.bean.GoodsOrderInfo;
import com.zaofan.bean.OrderPay;
import com.zaofan.constant.StateConstant;
import com.zaofan.constant.TypeConstant;
import com.zaofan.service.AccountService;
import com.zaofan.service.ErrorService;
import com.zaofan.service.GoodsOrderDetailService;
import com.zaofan.service.GoodsOrderInfoService;
import com.zaofan.service.GoodsService;
import com.zaofan.service.OrderPayService;
import com.zaofan.utils.C3p0DataSourceUtils;
import com.zaofan.utils.Constants;
import com.zaofan.utils.JPushUtils;
import com.zaofan.utils.SqlBuilderUtils;
import com.zaofan.utils.pay.MD5Util;

@WebServlet("/wei_pay_goods_notify")
public class WeiPayGoodsController extends HttpServlet {

	private static final long serialVersionUID = 5035453965360402957L;
	private GoodsOrderInfoService orderInfoService = new GoodsOrderInfoService();
	private OrderPayService orderPayService = new OrderPayService();

	private AccountService accountService = new AccountService();
	private AccountLog accountLog = new AccountLog();
	private ErrorService errorService = new ErrorService();
	private GoodsOrderDetailService orderDetailService = new GoodsOrderDetailService();
	private GoodsService productService = new GoodsService();

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.err.println("wei pay in ");
		try {
			SortedMap<Object, Object> map = parseXml(request);
			String sign = sign("UTF-8", map);
			if (sign.equals(map.get("sign"))) {
				System.err.println("签名正确");
				if ("SUCCESS".equals(map.get("result_code"))) {
					System.err.println("支付成功");
					String out_trade_no = (String) map.get("transaction_id");
					String orderNo = map.get("out_trade_no").toString().trim().split("t")[0];
					BigDecimal price = new BigDecimal((String) map.get("total_fee")).divide(new BigDecimal(100));
					GoodsOrderInfo order = orderInfoService.findByOrderNo(orderNo);
					if (order == null) {
						Error error = new Error();
						error.setAddTime(new Date());
						error.setError("微信支付出现问题,微信订单:" + orderNo + ",无法匹配不到系统的订单信息");
						error.setOrderNo(orderNo);
						errorService.add(error);
					} else {
						if (order.getPayState() == 2) {
							sendResult("SUCCESS", response);
							return;
						}
						Connection connection = C3p0DataSourceUtils.getConnection();
						Account account = accountService.findById(order.getAccountId());
						try {
							connection.setAutoCommit(false);
							// 更新订单状态
							String sql = "update " + GoodsOrderInfo.class.getSimpleName().toLowerCase()
									+ " set payState = " + StateConstant.ORDER_PAY_STATE_PAY + ",state = "
									+ StateConstant.ORDER_STATE_PAY + ",payType='微信支付',isTimeOut = 0 where orderNo = '"
									+ order.getOrderNo() + "'";
							QueryRunner runner = new QueryRunner();
							runner.update(connection, sql);
							Goods product;
							List<GoodsOrderDetail> details = orderDetailService.findByOrderId(order.getId());
							if (details != null && details.size() > 0)
								for (GoodsOrderDetail detail : details) {
									product = productService.findById(detail.getProductId());
									product.setDateCount(product.getDateCount() + detail.getProductCount());
									product.setSellcount(product.getSellcount() + detail.getProductCount());
									sql = SqlBuilderUtils.builderUpdateSql(Goods.class, product);
									runner.update(connection, sql);
								}

							// 增加订单支付记录
							OrderPay orderPay = new OrderPay();
							orderPay.setAddTime(new Date());
							orderPay.setOrderId(order.getId());
							orderPay.setOrderNo(order.getOrderNo());
							orderPay.setTradeNo(out_trade_no);
							orderPay.setPayMethod("微信支付");
							orderPay.setPayPrice(price);
							orderPay.setPayState("TRADE_SUCCESS");
							orderPay.setRemark("支付成功");
							sql = SqlBuilderUtils.builderInsertSql(OrderPay.class, orderPay);
							runner.update(connection, sql);
							if (price.compareTo(order.getPayPrice()) == 0) {
								// 微信支付
							} else {
								// 用户用余额支付一部分
								// 更新账户余额
								BigDecimal p = order.getPayPrice().subtract(price);
								if (account == null) {
									try {
										connection.rollback();
									} catch (SQLException e1) {
										e1.printStackTrace();
									}
									Error error = new Error();
									error.setAddTime(new Date());
									error.setError("微信支付出现问题,微信订单:" + out_trade_no + ",无法匹配不到系统的用户信息");
									error.setOrderNo(order.getOrderNo());
									errorService.add(error);
								} else {
									// 添加账户记录
									if (account.getMoney().compareTo(p) < 0) {
										Error error = new Error();
										error.setAddTime(new Date());
										error.setError("微信支付出现问题,微信订单:" + out_trade_no + ",用户的余额有误,账户余额:"
												+ account.getMoney() + ",支付宝支付金额:" + price);
										error.setOrderNo(order.getOrderNo());
										errorService.add(error);
									}
									AccountLog log = new AccountLog();
									log.setAccountId(account.getId());
									log.setAccountMobile(account.getMobile());
									log.setAddTime(new Date());
									log.setAfterMoney(account.getMoney().subtract(p));
									log.setBeforeMoney(account.getMoney());
									log.setMoney(p);
									log.setType(TypeConstant.log_type_yu_er_pay);
									account.setMoney(account.getMoney().subtract(p));
									sql = SqlBuilderUtils.builderInsertSql(AccountLog.class, log);
									runner.update(connection, sql);
									sql = "update account set money = "+ account.getMoney()
									+" where id = " + account.getId();
									runner.update(connection, sql);
									// 增加订单支付记录
									OrderPay orderPay1 = new OrderPay();
									orderPay1.setAddTime(new Date());
									orderPay1.setOrderId(order.getId());
									orderPay1.setOrderNo(order.getOrderNo());
									orderPay1.setTradeNo(out_trade_no);
									orderPay1.setPayMethod("账户余额支付");
									orderPay1.setPayPrice(p);
									orderPay1.setPayState("支付成功");
									orderPay1.setRemark("账户余额支付,余额不足,部分用微信支付");
									sql = SqlBuilderUtils.builderInsertSql(OrderPay.class, orderPay1);
									runner.update(connection, sql);
									
								}
							}
							connection.commit();
							JPushUtils.sendGoodsOrderSuccess(order, account);
						} catch (Exception e) {
							try {
								connection.rollback();
							} catch (SQLException e1) {
								e1.printStackTrace();
							}
							e.printStackTrace();
						} finally {
							try {
								connection.close();
							} catch (SQLException e) {
								e.printStackTrace();
							}
						}
					}
				} else {
					System.err.println("支付失败");
				}
				sendResult("SUCCESS", response);
				return;
			} else {
				System.err.println("签名失败");
			}
		} catch (Exception e2) {
		}
		sendResult("FAIL", response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

	public static SortedMap<Object, Object> parseXml(HttpServletRequest request) throws Exception {
		// 解析结果存储在HashMap
		SortedMap<Object, Object> map = new TreeMap<Object, Object>();
		InputStream inputStream = request.getInputStream();
		// 读取输入流
		SAXReader reader = new SAXReader();
		Document document = reader.read(inputStream);
		// 得到xml根元素
		Element root = document.getRootElement();
		// 得到根元素的所有子节点
		List<Element> elementList = root.elements();
		// 遍历所有子节点
		for (Element e : elementList)
			map.put(e.getName(), e.getText());
		// 释放资源
		inputStream.close();
		inputStream = null;
		return map;
	}

	public static String sign(String characterEncoding, SortedMap<Object, Object> parameters) {
		StringBuffer sb = new StringBuffer();
		Set es = parameters.entrySet();// 所有参与传参的参数按照accsii排序（升序）
		Iterator it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			Object v = entry.getValue();
			if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
				sb.append(k + "=" + v + "&");
			}
		}
		sb.append("key=" + Constants.API_KEY);
		String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
		return sign;
	}

	public void sendResult(String result, HttpServletResponse response) throws IOException {
		String s = "<xml><return_code><![CDATA[" + result
				+ "]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
		response.getWriter().println(s);
	}

}
